<?php

namespace App\Http\Controllers\Account;

use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Account\User;
use App\Helpers\Code;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\File;
use Intervention\Image\Facades\Image;

class UserController extends Controller
{

    private $avatarPath = 'avatars/';

    public function __construct()
    {
        $this->rules = [
            'username' => 'bail|required|max:20',
            'department_id' => 'bail|required|numeric',
            'phone' => array('bail', 'required', 'unique:users', 'regex:' . $this->pregPhone),
            'email' => 'bail|required|unique:users|email',
            'nickname' => 'max:20',
            'gender' => 'boolean',
            'job' => 'max:100',
            'scope_id' => 'bail|required|numeric',
            'parent_id' => 'bail|nullable|numeric',
            'identity_card' => 'bail|nullable|max:20',
            'telphone' => 'bail|nullable|max:200',
            'province' => 'bail|nullable|max:200',
            'city' => 'bail|nullable|max:200',
            'area' => 'bail|nullable|max:200',
            'address' => 'bail|nullable|max:200',
            'region' => 'bail|nullable|max:200',
            'region_province' => 'bail|nullable|max:200',
        ];

        $this->messages = [
            'username.required' => trans('user.username_required'),
            'username.max' => trans('user.username_max'),
            'department_id.required' => trans('user.department_id_required'),
            'department_id.numeric' => trans('user.department_id_numeric'),
            'phone.required' => trans('user.phone_required'),
            'phone.unique' => trans('user.phone_unique'),
            'phone.regex' => trans('user.regex_match'),
            'email.email' => trans('user.email_email'),
            'email.required' => trans('user.email_required'),
            'email.unique' => trans('user.email_unique'),
            'nickname.max' => trans('user.nickname_max'),
            'gender.boolean' => trans('user.gender_boolean'),
            'job.max' => trans('user.job_max'),
            'scope_id.required' => trans('user.scope_id_required'),
            'scope_id.numeric' => trans('user.scope_id_numeric'),
            'parent_id.numeric' => trans('user.parent_id_numeric'),
            'identity_card.max' => trans('user.identity_card_max'),
            'telphone.max' => trans('user.telphone_max'),
            'province.max' => trans('user.province_max'),
            'city.max' => trans('user.city_max'),
            'area.max' => trans('user.area_max'),
            'address.max' => trans('user.address_max'),
            'region.max' => trans('user.region_max'),
            'region_province.max' => trans('user.region_province_max'),
        ];

        $this->model = new User();
    }

    public function addUser(Request $request)
    {
        try {
            $data = $request->only(array_merge($this->model->getFillable(), ['usergroups']));

            if (isset($data['data_scope'])) {
                unset($data['data_scope']);
            }

            $validator = Validator::make($data, $this->rules, $this->messages);

            if ($validator->fails()) {
                return $this->error($validator, Code::SYSTEM_VALIDATOR_ERROR);
            }

            $groups = [];
            if (isset($data['usergroups'])) {
                if (!is_array($data['usergroups'])) {
                    return $this->error('common.data_format_error');
                }
                $groups = array_filter(array_unique($data['usergroups']));
                unset($data['usergroups']);
            }

            $data['password'] = Hash::make(config('system.user_default_password'));

            $model = $this->model->addUser($data, $groups);

            $this->checked($model, [
                Code::INSIDE_EXIST_DEPENDENCE => 'user.department_not_exists',
                Code::INSIDE_ERROR => 'user.superior_not_exists',
                Code::INSIDE_ERROR_1 => 'user.scope_not_exists',
                Code::INSIDE_FALSE => 'common.add_failure',
                Code::INSIDE_ERROR_2 => 'user.usergroup.user_group_not_exists',
            ]);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function deleteUser($id, Request $request)
    {
        try {
            if ($this->isMyself($id, $request->user()->id)) {
                return $this->error('user.user_delete_myself_failure');
            }

            $model = $this->model->deleteUserSoft($id);

            $this->checked($model, ['null' => 'common.delete_failure', Code::INSIDE_DATABASE_ERROR => 'common.database_error']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function editUser($id, Request $request)
    {
        try {
            $rules[] = '';
            $data = $request->only(array_merge($this->model->getFillable(), ['usergroups']));

            if (isset($data['password'])) {
                unset($data['password']);
            }

            if (isset($data['data_scope'])) {
                unset($data['data_scope']);
            }

            if (isset($data['usergroups'])) {
                if (!is_array($data['usergroups'])) {
                    return $this->error('common.data_format_error');
                }
                $data['usergroups'] = array_filter(array_unique($data['usergroups']));
            }

            foreach ($data as $key => $value) {
                switch ($key) {
                    case 'phone':
                        $rules['phone'] = ['bail', 'required', 'regex:/^(13[0-9]|14[57]|15[012356789]|16[6]|17[0678]|18[0-9])[0-9]{8}$/', \Illuminate\Validation\Rule::unique('users')->ignore($id)];
                        break;
                    case 'email':
                        $rules['email'] = ['bail', 'required', 'email', \Illuminate\Validation\Rule::unique('users')->ignore($id)];
                        break;
                    case 'usergroups':
                        break;
                    default :
                        $rules[$key] = $this->rules[$key];
                }
            }
            $validator = Validator::make($data, $rules, $this->messages);

            if ($validator->fails()) {
                return $this->error($validator, Code::SYSTEM_VALIDATOR_ERROR);
            }

            $model = $this->model->editUser($id, $data);

            $this->checked($model, [
                'null' => 'common.recored_not_found',
                Code::INSIDE_EXIST_DEPENDENCE => 'common.edit_failure',
                Code::INSIDE_ERROR => 'user.superior_not_exists',
                Code::INSIDE_ERROR_1 => 'user.scope_not_exists',
                Code::INSIDE_ERROR_2 => 'user.usergroup.user_group_not_exists',
                Code::INSIDE_DATABASE_ERROR => 'common.database_error',
            ]);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getUserList(Request $request)
    {
        try {
            $search = $this->handleSearch($request, $this->model);

            $limit = (int) $request->input('limit');

            $sorter = $this->handleSort($request, $this->model->sorters);

            $model = $this->model->getUserList($limit, $sorter, $search);

            return preprocess($model);
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getUserListAll()
    {
        try {
            $model = $this->model->getUserListAll();

            $this->result['data'] = $model;

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getEditUser($id)
    {
        try {
            $model = $this->model->getEditUser($id);

            $this->checked($model, ['null' => 'common.get_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getUser($id)
    {
        try {
            $model = $this->model->getUser($id);

            $this->checked($model, ['null' => 'common.get_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getCurrentUser($id, Request $request)
    {
        try {
            if ($this->isMyself($id, $request->user()->id)) {

                $model = $this->model->getCurrentUser($id);

                $this->checked($model, ['null' => 'common.get_failure']);

                return $this->result;
            }

            return $this->error('user.no_self_operation');
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function blockUser($id, Request $request)
    {
        try {
            if ($this->isMyself($id, $request->user()->id)) {
                return $this->error('user.user_block_unblock_failure');
            }

            $model = $this->model->blockUser($id);

            $this->checked($model, ['null' => 'user.user_block_failure', Code::INSIDE_ERROR => 'user.user_already_block']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function unblockUser($id, Request $request)
    {
        try {
            if ($this->isMyself($id, $request->user()->id)) {
                return $this->error('user.user_block_unblock_failure');
            }

            $model = $this->model->unblockUser($id);

            $this->checked($model, ['null' => 'user.user_unblock_failure', Code::INSIDE_ERROR => 'user.user_already_unblock']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function editPassword($id, Request $request)
    {
        try {
            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            $data = $request->only(['old_password', 'password', 'password_confirmation']);
            $rules = array(
                'old_password' => 'required|alpha_dash|between:6,16',
                'password' => 'required|alpha_dash|between:6,16|confirmed',
            );

            $messages = [
                'password.required' => trans('user.password_required'),
                'password.alpha_dash' => trans('user.password_alpha_dash'),
                'password.between' => trans('user.password_between'),
                'password.confirmed' => trans('user.password_confirmed'),
                'old_password.required' => trans('user.old_password_required'),
                'old_password.alpha_dash' => trans('user.old_password_alpha_dash'),
                'old_password.between' => trans('user.old_password_between'),
            ];

            $validator = Validator::make($data, $rules, $messages);

            if ($validator->fails()) {
                return $this->error($validator, Code::SYSTEM_VALIDATOR_ERROR);
            }

            if (!$this->model->checkPassword($id, $data)) {
                return $this->error('user.password_not_same');
            }

            $model = $this->model->editPassword($id, e(Hash::make($request->input('password'))));

            $this->checked($model, ['bull' => 'common.recored_not_found']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function uploadAvatar($id, Request $request)
    {
        try {
            $rules = ['file' => 'bail|required|mimes:jpeg,gif,png|max:1024'];

            $messages = [
                'file.required' => trans('user.file_required'),
                'file.mimes' => trans('user.file_mimes'),
                'file.max' => trans('user.file_max'),
            ];

            $validator = Validator::make($request->all(), $rules, $messages);

            if ($validator->fails()) {
                return $this->error($validator, Code::SYSTEM_VALIDATOR_ERROR);
            }

            $user = $this->model->isExist($id);

            if (!$user) {
                return $this->error('common.recored_not_found');
            }

            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            $file = $request->file('file');

            $ext = $file->guessClientExtension();
            $fullname = $file->getClientOriginalName();
            $hashname = date('H.i.s') . '-' . md5($fullname) . '.' . $ext;

            $avatar = Image::make($file->getRealPath());

            $avatar->resize(196, 196)->save(public_path($this->avatarPath . $hashname));

            $model = $this->model->uploadAvatar($id, $hashname);

            if (!$model) {
                return $this->error('common.add_failure');
            }

            File::delete($this->avatarPath . $user->avatar);

            $this->result['data'] = asset($this->avatarPath . $hashname);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function deleteAvatar($id, Request $request)
    {
        try {
            $user = $this->model->isExist($id);
            if (!$user) {
                return $this->error('common.recored_not_found');
            }

            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            File::delete($this->avatarPath . $user->avatar);

            $model = $this->model->deleteAvatar($id);

            $this->checked($model, ['null' => 'common.delete_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 获取用户信息
     * @param $id
     * @return array
     */
    public function getCurrentUserInfo($id, Request $request)
    {
        try {
            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            $model = $this->model->getCurrentUserInfo($id);

            $this->checked($model, ['null' => 'common.get_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 个人信息修改
     * @param $id   个人id
     * @param Request $request
     * @return array
     */
    public function editCurrentUserInfo($id, Request $request)
    {
        try {
            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            $rules[] = '';

            $data = $request->only(['username', 'nickname', 'job', 'email', 'gender']);

            foreach ($data as $key => $value) {
                switch ($key) {
                    case 'phone':
                        $rules['phone'] = ['bail', 'required', 'regex:/^(13[0-9]|14[57]|15[012356789]|17[0678]|18[0-9])[0-9]{8}$/', \Illuminate\Validation\Rule::unique('users')->ignore($id)];
                        break;
                    case 'email':
                        $rules['email'] = ['bail', 'required', 'email', \Illuminate\Validation\Rule::unique('users')->ignore($id)];
                        break;
                    default :
                        $rules[$key] = $this->rules[$key];
                }
            }

            $validator = Validator::make($data, $rules, $this->messages);
            if ($validator->fails()) {
                return $this->error($validator, Code::SYSTEM_VALIDATOR_ERROR);
            }

            $model = $this->model->editCurrentUserInfo($id, $data);

            $this->checked($model, ['null' => 'common.edit_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function getUserMenuList($id, Request $request)
    {
        try {
            if (!$this->isMyself($id, $request->user()->id)) {
                return $this->error('user.no_self_operation');
            }

            $model = $this->model->getUserMenuList($id);

            $this->result['data'] = $model;

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 删除用户菜单缓存
     * @param $id
     * @return array
     */
    public function clearUserCache($id)
    {
        try {
            $model = $this->model->clearUserCache($id);

            $this->checked($model, ['null' => 'common.recored_not_found']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 删除用户token
     * @param $id
     * @return array
     */
    public function clearUserToken($id)
    {
        try {
            $model = $this->model->clearUserToken($id);

            $this->checked($model, ['null' => 'common.recored_not_found']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 用户初始化密码
     * @param $id
     * @return array
     */
    public function resetUserPassword($id)
    {
        try {
            $model = $this->model->resetUserPassword($id);

            $this->checked($model, ['null' => 'common.recored_not_found']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 获取用户登录信息列表
     * @param $id
     * @param Request $request
     * @return array
     */
    public function getUserLoginLogList($id, Request $request)
    {
        try {
            $limit = (int) $request->input('limit');

            $sorter = $this->handleSort($request, ['created_at']);

            $model = $this->model->getUserLoginLogList($limit, $sorter, $id);
            if ($model === null) {
                return $this->error('common.recored_not_found');
            }

            return preprocess($model);
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 获取用户操作信息列表
     * @param $id
     * @param Request $request
     * @return array
     */
    public function getUserOperationLogList($id, Request $request)
    {
        try {
            $limit = (int) $request->input('limit');

            $sorter = $this->handleSort($request, ['created_at']);

            $search = $request->only(['start_time', 'end_time']);
            $model = $this->model->getUserOperationLogList($limit, $sorter, $search, $id);
            if ($model === null) {
                return $this->error('common.recored_not_found');
            }

            return preprocess($model);
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 获取用户权限
     * @param $id
     * @return array
     */
    public function getUserPermission($id)
    {
        try {
            $model = $this->model->getUserPermission($id);

            $this->checked($model, ['null' => 'common.recored_not_found']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    /**
     * 删除用户token   *****暂时未使用******
     * @param $id
     * @return array
     */
    public function deleteToken($id)
    {
        try {
            $user = $this->model->deleteToken($id);

            if (!$user) {
                return $this->error('common.delete_failure');
            }

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function resetUserCache()
    {
        try {
            $model = $this->model->resetUserCache();

            $this->checked($model, [Code::INSIDE_DATABASE_ERROR => 'common.database_error']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

    public function clearUserAvatar($id)
    {
        try {
            $user = $this->model->isExist($id);
            if (!$user) {
                return $this->error('common.recored_not_found');
            }

            File::delete($this->avatarPath . $user->avatar);

            $model = $this->model->clearUserAvatar($id);

            $this->checked($model, ['null' => 'common.delete_failure']);

            return $this->result;
        } catch (\Exception $e) {
            return $this->throwError($e);
        }
    }

}
